package com.eshop.modules.security.rest;

import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.http.HttpStatus;
import java.util.concurrent.TimeUnit;
import cn.hutool.core.util.IdUtil;
import com.wf.captcha.ArithmeticCaptcha;
import org.springframework.web.bind.annotation.GetMapping;
import com.eshop.utils.SecurityUtils;
import org.springframework.web.bind.annotation.PostMapping;
import com.eshop.annotation.AnonymousAccess;
import io.swagger.annotations.ApiOperation;
import com.eshop.logging.aop.log.Log;
import java.util.Map;
import java.util.HashMap;
import com.eshop.modules.security.security.vo.JwtUser;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.Authentication;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import com.eshop.exception.BadRequestException;
import com.eshop.utils.StringUtils;
import cn.hutool.crypto.asymmetric.KeyType;
import cn.hutool.crypto.asymmetric.RSA;
import org.springframework.http.ResponseEntity;
import javax.servlet.http.HttpServletRequest;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.validation.annotation.Validated;
import com.eshop.modules.security.security.vo.AuthUser;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import com.eshop.modules.security.security.TokenUtil;
import com.eshop.modules.security.service.OnlineUserService;
import org.springframework.security.core.userdetails.UserDetailsService;
import com.eshop.utils.RedisUtils;
import com.eshop.modules.security.config.SecurityProperties;
import org.springframework.beans.factory.annotation.Value;
import org.slf4j.Logger;
import io.swagger.annotations.Api;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping({ "/auth" })
@Api(tags = { "系统：系统授权接口" })
public class AuthController
{
    private static final Logger log;
    @Value("${loginCode.expiration}")
    private Long expiration;
    @Value("${rsa.private_key}")
    private String privateKey;
    @Value("${single.login}")
    private Boolean singleLogin;
    @Value("${product.company}")
    private String productCompany;
    private final SecurityProperties properties;
    private final RedisUtils redisUtils;
    private final UserDetailsService userDetailsService;
    private final OnlineUserService onlineUserService;
    private final TokenUtil tokenUtil;
    private final AuthenticationManagerBuilder authenticationManagerBuilder;
    
    public AuthController(final SecurityProperties properties, final RedisUtils redisUtils, final UserDetailsService userDetailsService, final OnlineUserService onlineUserService, final TokenUtil tokenUtil, final AuthenticationManagerBuilder authenticationManagerBuilder) {
        this.properties = properties;
        this.redisUtils = redisUtils;
        this.userDetailsService = userDetailsService;
        this.onlineUserService = onlineUserService;
        this.tokenUtil = tokenUtil;
        this.authenticationManagerBuilder = authenticationManagerBuilder;
    }
    
    @Log("用户登录")
    @ApiOperation("登录授权")
    @AnonymousAccess
    @PostMapping({ "/login" })
    public ResponseEntity<Object> login(@Validated @RequestBody final AuthUser authUser, final HttpServletRequest request) {
        final RSA rsa = new RSA(this.privateKey, null);
        System.out.println("Password: " +authUser.getPassword());
//        final String password = new String(rsa.decrypt(authUser.getPassword(), KeyType.PrivateKey));
        String password = authUser.getPassword();
        final String code = (String)this.redisUtils.get(authUser.getUuid());
        this.redisUtils.del(new String[] { authUser.getUuid() });
        if (StringUtils.isBlank(code)) {
            throw new BadRequestException("验证码不存在或已过期");
        }
        if (StringUtils.isBlank((CharSequence)authUser.getCode()) || !authUser.getCode().equalsIgnoreCase(code)) {
            throw new BadRequestException("验证码错误");
        }
        final UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(authUser.getUsername(), password);
        final Authentication authentication = (this.authenticationManagerBuilder.getObject()).authenticate(authenticationToken);
        SecurityContextHolder.getContext().setAuthentication(authentication);
        final UserDetails userDetails = (UserDetails)authentication.getPrincipal();
        final String token = this.tokenUtil.generateToken(userDetails);
        final JwtUser jwtUser = (JwtUser)authentication.getPrincipal();
        this.onlineUserService.save(jwtUser, token, request);
        final Map<String, Object> authInfo = new HashMap<String, Object>(2) {
            {
                this.put("token", AuthController.this.properties.getTokenStartWith() + token);
                this.put("user", jwtUser);
            }
        };
        if (this.singleLogin) {
            this.onlineUserService.checkLoginOnUser(authUser.getUsername(), token);
        }
        return ResponseEntity.ok(authInfo);
    }
    
    @ApiOperation("获取用户信息")
    @GetMapping({ "/info" })
    public ResponseEntity<Object> getUserInfo() {
        final JwtUser jwtUser = (JwtUser)this.userDetailsService.loadUserByUsername(SecurityUtils.getUsername());
        return ResponseEntity.ok(jwtUser);
    }
    
    @AnonymousAccess
    @ApiOperation("获取验证码")
    @GetMapping({ "/code" })
    public ResponseEntity<Object> getCode() {
        final ArithmeticCaptcha captcha = new ArithmeticCaptcha(111, 36);
        captcha.setLen(2);
        String result = "";
        try {
            result = new Double(Double.parseDouble(captcha.text())).intValue() + "";
        }
        catch (Exception e) {
            result = captcha.text();
        }
        final String uuid = this.properties.getCodeKey() + IdUtil.simpleUUID();
        this.redisUtils.set(uuid, result, (long)this.expiration, TimeUnit.MINUTES);
        final Map<String, Object> imgResult = new HashMap<String, Object>(2) {
            {
                (this).put("img", captcha.toBase64());
                (this).put("uuid", uuid);
                (this).put("productCompany", AuthController.this.productCompany);
            }
        };
        return ResponseEntity.ok(imgResult);
    }

    @ApiOperation("退出登录")
    @AnonymousAccess
    @DeleteMapping({ "/logout" })
    public ResponseEntity<Object> logout(final HttpServletRequest request) {
        this.onlineUserService.logout(this.tokenUtil.getToken(request));
        return new ResponseEntity(HttpStatus.OK);
    }
    
    static {
        log = LoggerFactory.getLogger((Class)AuthController.class);
    }
}
